package com.sky.apotion;



import com.sky.autofill.fill;
import com.sky.enumeration.OperationType;
import com.sky.utils.ThroadLocal;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.time.LocalDateTime;

import static com.sky.constant.AutoFillConstant.*;

@Component
@Aspect
@Slf4j
public class autofillapect {


    @Before("@annotation(com.sky.autofill.fill)")
    public void Fill(JoinPoint joinPoint) {
        try {
            Object[] args = joinPoint.getArgs();

            Object object = args[0];

            long updateUser = ThroadLocal.get();

            LocalDateTime localDateTime = LocalDateTime.now();
            MethodSignature signature = (MethodSignature) joinPoint.getSignature();
            fill f = signature.getMethod().getAnnotation(fill.class);
            OperationType operationType = f.value();



            if (operationType == OperationType.INSERT) {
                Method setCreateUser = object.getClass().getDeclaredMethod(SET_CREATE_USER, Long.class);
                Method setCreateTime = object.getClass().getDeclaredMethod(SET_CREATE_TIME, LocalDateTime.class);
                Method setUpdateUser = object.getClass().getDeclaredMethod(SET_UPDATE_USER, Long.class);
                Method setUpdateTime = object.getClass().getDeclaredMethod(SET_UPDATE_TIME, LocalDateTime.class);
                setCreateUser.setAccessible(true);
                setCreateTime.setAccessible(true);
                setUpdateUser.setAccessible(true);
                setUpdateTime.setAccessible(true);
                setCreateUser.invoke(object,  updateUser);
                setCreateTime.invoke(object, localDateTime);
                setUpdateUser.invoke(object, updateUser);
                setUpdateTime.invoke(object, localDateTime);
            } else if (operationType == OperationType.UPDATE) {

                Method setUpdateUser = object.getClass().getDeclaredMethod(SET_UPDATE_USER, Long.class);
                Method setUpdateTime = object.getClass().getDeclaredMethod(SET_UPDATE_TIME, LocalDateTime.class);
                setUpdateUser.setAccessible(true);
                setUpdateTime.setAccessible(true);
                setUpdateUser.invoke(object, updateUser);
                setUpdateTime.invoke(object, localDateTime);
            }
        } catch (NoSuchMethodException e) {
            log.error("Method not found during autofill aspect execution", e);
            throw new RuntimeException("Method not found during autofill aspect execution", e);
        } catch (InvocationTargetException e) {
            log.error("Invocation target exception during autofill aspect execution", e.getTargetException());
            throw new RuntimeException("Invocation target exception during autofill aspect execution", e.getTargetException());
        } catch (IllegalAccessException e) {
            log.error("Illegal access exception during autofill aspect execution", e);
            throw new RuntimeException("Illegal access exception during autofill aspect execution", e);
        } catch (Exception e) {
            log.error("Unexpected exception during autofill aspect execution", e);
            throw new RuntimeException("Unexpected exception during autofill aspect execution", e);
        }
    }

}